#include "stdafx.h"
#include "Utility.h"
#include "CommandConsts.h"
#include "CommandDispatcher.h"
#include "BattleLogic.h"
#include "Scene.h"
#include "ProcessManager.h"
#include "Actor.h"
#include "MemTrack.h"

namespace bs
{
	BattleLogic::BattleLogic(Scene* scene) : scene(scene)
	{
		this->delayTimer = 0;
	}

	BattleLogic::~BattleLogic()
	{
	}

	void BattleLogic::Run(int id, size_t time, size_t frames, size_t elapse, void* userData)
	{	
		if(this->delayTimer != id)
			return;

		ProcessManager::Instance().TerminateProcess(this->delayTimer);
		this->delayTimer = 0;

		if(this->scene->state == Scene::WAIT_PLACE_SEL)
		{
			this->PlaceEnemy();
		}
		else
		{
			this->UpdateEnemy();
		}
	}

	void BattleLogic::Update( size_t time, size_t frames, size_t elapse )
{
		if(this->scene->playerTurn || this->scene->waitAnim)
			return;

		if(this->scene->state!=Scene::FREE_CONTROL && this->scene->state!=Scene::WAIT_PLACE_SEL)
			return;

		if(this->delayTimer == 0)
		{
			ProcessManager::Instance().NewProcess(&this->delayTimer, this, ProcessManager::Time, 
				ProcessManager::Normal, time+1200, 1, 1, NULL);
		}
	}

	void BattleLogic::PlaceEnemy()
	{
		BattleGround& bg = this->scene->GetBattleGround();

		Point pos(-1, -1);
		int actorCnt = bg.GetRow() * bg.GetCol();
		int begin = ::rand()%actorCnt;
		for(int i=0; i<actorCnt; ++i)
		{
			int index = (i+begin) % actorCnt;
			pos.x = index%bg.GetCol();
			pos.y = index/bg.GetCol();
			if(!bg.GetActor(pos))
			{
				break;
			}
		}
		
		if(pos.x >= 0)
		{
			ActorCfg ac = this->scene->actorCfgs[::rand()%this->scene->actorCfgs.size()];

			Actor* a = new Actor(bg, false);
			a->Init(ac.hp, ac.mp, ac.at, ac.df, ac.as);
			a->SetImage(ac.imageFile.c_str());
			a->Place(pos.x, pos.y);
			a->SetShow(false);
			this->scene->actionOrder.push_back(a);
		}

		this->scene->waitAnim = true;
	}

	void BattleLogic::UpdateEnemy()
	{
		BattleGround& bg = this->scene->GetBattleGround();

		Actor* actor = this->scene->GetCurActor();

		const std::vector<Point>& attacks = actor->GetAttackablePoints();
		if(attacks.size())
		{
		    std::vector<Point>::const_iterator itr=attacks.begin();

			Actor* enemy = NULL;
			Actor* maxHpEnemy = bg.GetActor(*itr);
			Actor* minHpEnemy = maxHpEnemy;
			Actor* maxAtEnemy = maxHpEnemy;

			++ itr;
			while(itr != attacks.end())
			{
				enemy = bg.GetActor(*itr);

				if(enemy->GetHp() >= maxHpEnemy->GetHp())
				{
					maxHpEnemy = enemy;
				}
				else
				{
					minHpEnemy = enemy;
				}

				if(enemy->GetAt() >= maxAtEnemy->GetAt())
				{
					maxAtEnemy = enemy;
				}

				++ itr;
			}

			if(actor->LikeAttackMaxHp())
			{
				enemy = maxHpEnemy;
			}
			else if(actor->LikeAttackMinHp())
			{
				enemy = minHpEnemy;
			}
			else
			{
				enemy = maxAtEnemy;
			}

			actor->Attack(enemy);

			this->scene->waitAnim = true;

			return;
		}

		const std::vector<Point>& moves = actor->GetMoveablePoints();
		if(moves.size())
		{
			Point to = moves[::rand()%moves.size()];
			actor->MoveTo(to);

			actor->SetShow(false);

			this->scene->waitAnim = true;

			return;
		}

		this->scene->AdvanceToNextState();
	}

}
